﻿/***************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@gmail.com)

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/

using System;
using System.Collections.ObjectModel;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using ComponentArt.Web.UI;

namespace BaoJianSoft.Web.Extensions.Controls
{
	/// <summary>
	/// Filterable combobox web control.
	/// </summary>
	public abstract class FilteredComboBox : Panel, INamingContainer, IPostBackEventHandler
	{
		private ComboBox comboBox;

		/// <summary>
		/// Construct FilteredComboBox instance.
		/// </summary>
		public FilteredComboBox()
		{
			this.RaiseSelectedIndexChangeEvent = true;
		}

		/// <summary>
		/// Sets/gets event when combobox selected index changed.
		/// </summary>
		public event EventHandler SelectedIndexChanged;

		/// <summary>
		/// Sets/gets true to raise event SelectedIndexChange. The default value is false.
		/// </summary>
		public bool RaiseSelectedIndexChangeEvent { get; set; }

		/// <summary>
		/// Gets collection of list items
		/// </summary>
		public OptionCollection Items 
		{
			get 
			{
				if (this.ViewState["Items"] == null)
				{
					this.ViewState["Items"] = new OptionCollection();
				}

				return this.ViewState["Items"] as OptionCollection;
			}
		}

		private bool setEnabled;
		/// <summary>
		/// Sets/gets true to enable filtered combobox.
		/// </summary>
		public override bool Enabled
		{
			get
			{
				if (this.setEnabled) return (bool)this.ViewState["Enabled"];
				return this.comboBox.Enabled;
			}
			set
			{
				this.ViewState["Enabled"] = value;
				this.setEnabled = true;
			}
		}

		private bool setSelectedValue;
		/// <summary>
		/// Sets/gets selected value.
		/// </summary>
		public string SelectedValue 
		{
			get 
			{
				if (this.setSelectedValue) return this.ViewState["SelectedValue"] as string;
				if (this.comboBox.SelectedIndex >= 0 && this.Items.Count > 0)
					return this.Items[this.comboBox.SelectedIndex].Value;

				return this.comboBox.SelectedValue;
			}
			set 
			{ 
				this.ViewState["SelectedValue"] = value;
				this.setSelectedValue = true;
			}
		}

		private bool setSelectedIndex;
		/// <summary>
		/// Sets/gets selected index.
		/// </summary>
		public int SelectedIndex
		{
			get 
			{
				if (this.setSelectedIndex) return (int)this.ViewState["SelectedIndex"];
				return this.comboBox.SelectedIndex;
			}
			set
			{
				this.ViewState["SelectedIndex"] = value;
				this.setSelectedIndex = true;
			}
		}

		private bool setSelectedText;
		/// <summary>
		/// Sets/gets selected text.
		/// </summary>
		public string SelectedText
		{
			get
			{
				if (this.setSelectedText) return this.ViewState["SelectedText"] as string;
				return this.comboBox.Text;
			}
			set
			{
				this.ViewState["SelectedText"] = value;
				this.setSelectedText = true;
			}
		}

		private bool setAutoPostBack;
		/// <summary>
		/// Sets/gets true when the control is auto postback.
		/// </summary>
		public bool AutoPostBack
		{
			get 
			{
				if (this.ViewState["AutoPostBack"] == null) return false;
				return (bool)this.ViewState["AutoPostBack"];
			}
			set 
			{
				this.ViewState["AutoPostBack"] = value;
				this.setAutoPostBack = true;
			}
		}

		private bool setAutoComplete;
		/// <summary>
		/// Sets/gets true when the control is auto complete. The default value is true.
		/// </summary>
		public bool AutoComplete
		{
			get
			{
				if (this.ViewState["AutoComplete"] == null) return true;
				return (bool)this.ViewState["AutoComplete"];
			}
			set
			{
				this.ViewState["AutoComplete"] = value;
				this.setAutoComplete = true;
			}
		}

		/// <summary>
		/// Sets/gets true when the control is required.
		/// </summary>
		public bool IsRequiredField
		{
			get
			{
				if (this.ViewState["IsRequiredField"] == null) return false;
				return (bool)this.ViewState["IsRequiredField"];
			}
			set
			{
				this.ViewState["IsRequiredField"] = value;
			}
		}

		/// <summary>
		/// Sets/gets true if datasource of control is initialized.
		/// </summary>
		public bool Initialized
		{
			get
			{
				if (base.ViewState["Initialized"] == null) return false;
				return (bool)base.ViewState["Initialized"];
			}
			set { base.ViewState["Initialized"] = value; }
		}

		protected override void OnInit(EventArgs e)
		{
			this.comboBox = new ComboBox();
		}

		protected override void OnLoad(EventArgs e)
		{
			this.comboBox.EnableViewState = true;
			this.comboBox.ID = "ComboBox";
			this.comboBox.Visible = true;
			this.comboBox.SelectedIndexChanged += new ComboBox.SelectedIndexChangedEventHandler(OnComboBoxSelectedIndexChanged);
			this.comboBox.AutoFilter = true;
			this.comboBox.AutoHighlight = false;
			this.comboBox.AutoComplete = true;
			this.comboBox.CssClass = "comboBox";
			this.comboBox.HoverCssClass = "comboBoxHover";
			this.comboBox.FocusedCssClass = "comboBoxHover";
			this.comboBox.TextBoxCssClass = "comboTextBox";
			this.comboBox.TextBoxDisabledCssClass = "comboDisabledTextBox";
			this.comboBox.DropDownCssClass = "comboDropDown";
			this.comboBox.ItemCssClass = "comboItem";
			this.comboBox.ItemHoverCssClass = "comboItemHover";
			this.comboBox.SelectedItemCssClass = "comboItemHover";
			this.comboBox.DropHoverImageUrl = this.GetImageUrl("drop_hover.gif");
			this.comboBox.DropImageUrl = this.GetImageUrl("drop.gif");
			this.comboBox.DropDownHeight = 160;
			this.comboBox.DropDownWidth = 150;
			this.comboBox.Width = new Unit("154px");

			if (!this.IsRequiredField)
			{
				this.Controls.Add(this.comboBox);
			}
			else
			{
				HtmlTable htmlTable = new HtmlTable { CellPadding = 0, CellSpacing = 0, Width = "99%" };
				this.Controls.Add(htmlTable);

				HtmlTableRow htmlTableRow = new HtmlTableRow();
				htmlTable.Rows.Add(htmlTableRow);

				HtmlTableCell htmlTableCell = new HtmlTableCell { Width = this.comboBox.Width.ToString() };
				htmlTableRow.Cells.Add(htmlTableCell);
				htmlTableCell.Controls.Add(this.comboBox);

				htmlTableCell = new HtmlTableCell();
				htmlTableRow.Cells.Add(htmlTableCell);
				HtmlGenericControl spanRedStar = new HtmlGenericControl("span") { InnerText = "*" };
				spanRedStar.Attributes["class"] = "red";
				htmlTableCell.Controls.Add(spanRedStar);
			}

			if (!Page.IsPostBack || !this.Initialized)
			{
				this.Initialized = true;
				this.LoadDataSource();
			}

			base.OnLoad(e);
		}

		protected override void OnPreRender(EventArgs e)
		{
			if (this.Items.Count != this.comboBox.Items.Count)
			{
				this.comboBox.Text = "";
				this.comboBox.SelectedIndex = -1;
				this.comboBox.Items.Clear();
				foreach (Option listItem in this.Items)
				{
					this.comboBox.Items.Add(new ComboBoxItem() { Text = listItem.Text, Value = listItem.Value, Selected = listItem.Selected });
				}
			}

			if (this.setSelectedValue) this.comboBox.SelectedValue = this.SelectedValue;
			if (this.setSelectedText) this.comboBox.Text = this.SelectedText;
			if (this.setSelectedIndex) this.comboBox.SelectedIndex = this.SelectedIndex;
			if (this.setAutoPostBack) this.comboBox.AutoPostBack = this.AutoPostBack;
			if (this.setAutoComplete) this.comboBox.AutoComplete = this.AutoComplete;
			if (this.setEnabled) this.comboBox.Enabled = this.Enabled;

			base.OnPreRender(e);
		}

		/// <summary>
		/// Load datasource of control.
		/// </summary>
		protected abstract void LoadDataSource();

		private void OnComboBoxSelectedIndexChanged(object sender, EventArgs e)
		{
			if (this.SelectedIndexChanged != null && this.RaiseSelectedIndexChangeEvent)
			{
				this.SelectedIndexChanged(this, new EventArgs());
			}
		}

		private string GetImageUrl(string fileName)
		{
			return string.Format("/App_Themes/{0}/Controls/ComboBox/{1}", this.Page.Theme, fileName);
		}

		#region IPostBackEventHandler Members

		void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
		{
			if (eventArgument.ToLower() == "selectedindexchanged" && this.SelectedIndexChanged != null && this.RaiseSelectedIndexChangeEvent)
			{
				this.SelectedIndexChanged(this, new EventArgs());
			}
		}

		#endregion
	}

	/// <summary>
	/// Option collection class.
	/// </summary>
	[Serializable]
	public class OptionCollection : Collection<Option>
	{
	}
}
